package com.qf.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: JwtUtils
 * @Author: WangHao
 * @Date: 2025/5/7 19:15
 * @Description:
 * @Version: 1.0
 */
@Component
public class JwtUtils {
    // 密钥
    // 令牌自定义标识
    @Value("${token.header}")
    private String header;

    // 令牌秘钥
    @Value("${token.secret}")
    private String secret;

    // 令牌有效期（默认30分钟）
    @Value("${token.expireTime}")
    private int expireTime;

    @Autowired
    private RedisUtil redisUtil;
    /**
     */
    public String createJwt(Map<String, Object> claims) {

        // 创建唯一id
        String uuid = UUID.randomUUID().toString().replace("-", "");
        claims.put("uuid", uuid);

        // 签名算法，表示sha256
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        //构造jwt
        JwtBuilder builder = Jwts.builder( )//.setHeaderParam("type","jwt") // 设置头
                .setClaims(claims) // 设置载荷
                // 存到redis中，就不需要设置token过期时间了
                // .setExpiration(new Date(System.currentTimeMillis( ) + expireTime * 1000 * 60)) // 设置过期时间
                .signWith(signatureAlgorithm, secret); // 使用指定算法设置签名
        //生成jwt token
        String token = builder.compact();
        //存入redis
        redisUtil.setCacheObject("user:key:"+uuid, token, expireTime, TimeUnit.MINUTES);
        return token;

    }

    /**
     * 解析，如果不符合，报异常
     *
     * @param jsonWebToken
     * @return
     */
    public Claims parseJWT(String jsonWebToken) {

        // 判断距离上次操作是否过期，从redis中获取


        try {
            Claims claims = Jwts.parser( )
                    .setSigningKey(secret)
                    .parseClaimsJws(jsonWebToken).getBody( );
            return claims;
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage( ));
        }
    }

    public String getToken(HttpServletRequest request) {
        String token = request.getHeader(header);
        if (StringUtils.hasText(token)) {
            return token;
        }
        return null;
    }

    // 验证token 验证此次请求有没有超时
    public boolean validateToken(String token) {
        Claims claims = Jwts.parser( )
                .setSigningKey(secret)
                .parseClaimsJws(token).getBody( ); // 获取token
        Object uuid = claims.get("uuid"); // 获取uuid
        Object redisToken = redisUtil.getCacheObject("user:key:" + uuid);// 获取redis中的token
        if(redisToken == null || !redisToken.equals(token))
        {
            throw new AccessDeniedException("token校验失败");
        }
        return true;
    }

    // 刷新token时间
    public void refreshToken(String token) {
        Claims claims = Jwts.parser( )
                .setSigningKey(secret)
                .parseClaimsJws(token).getBody( );
        Object uuid = claims.get("uuid");
        // 刷新redis中的token
        redisUtil.setCacheObject("user:key:"+uuid, token, expireTime, TimeUnit.MINUTES);
    }
}
